﻿using System.Collections.Generic;
using System.Linq;
using Algoritmia.Problems.Puzzles.NQueens;
using Algoritmia.Utils;

namespace Demos.Problems.Nqueens
{
    class ObservableNQueensEnumerator5 : SpecialNQueensEnumerator
    {
        public event ReinaHandler ColocarReina;
        public event ReinaHandler RetirarReina;

        override protected IEnumerable<Algoritmia.DataStructures.Lists.IList<int>> Backtracking(NQueensStateSpace4.State state,
            NQueensStateSpace4 space, Algoritmia.DataStructures.Lists.IList<int> decisions)
        {
            if (space.IsFinal(state))
            {
                yield return decisions;
            }
            foreach (var decision in space.Decisions(state))
            {
                decisions.Add(decision);
                if (ColocarReina != null) ColocarReina(decision);
                state = space.Decide(state, decision);
                foreach (var result in Backtracking(state, space, decisions))
                {
                    yield return result;
                }
                if (RetirarReina != null) RetirarReina(decisions.Last());
                decisions.RemoveAt(decisions.Count - 1);
                state = space.Undo(state, decision);
            }
        }

        public override IEnumerable<Algoritmia.DataStructures.Lists.IList<int>> Enumerate(NQueensStateSpace4 space)
        {
            if (space is NQueensStateSpace5)
            {
                foreach (var solution in base.Enumerate(space))
                {
                    yield return solution;
                    if (solution[0] < space.N / 2)
                    {
                        ColocarReina = null;
                        RetirarReina = null;
                        yield return solution.Select(i => space.N - i - 1).ToAlgoritmiaList();
                    }
                }
            }
            else
            {
                foreach (var solution in base.Enumerate(space))
                {
                    ColocarReina = null;
                    RetirarReina = null;
                    yield return solution;
                }
            }

        }
    }
}
